/////////////////////////////////////////////     File     //////////////////////////////////////////////////
// Author: James Chen
// Filename: BallisticCalculator.cpp
// Created: Sunday, October 17, 2010 9:22:30 AM
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "./CBallisticCalculator.h"

////////////////////// Singleton Implementation Begins //////////////////////
CBallisticCalculator *CBallisticCalculator::m_pInstance = 0;

CBallisticCalculator::CBallisticCalculator(void)
{
	this->PopulateDragModels();
}

CBallisticCalculator::~CBallisticCalculator(void)
{
}

CBallisticCalculator *CBallisticCalculator::GetInstance(void)
{
	if(!m_pInstance)
	{
		m_pInstance = new CBallisticCalculator;
	}

	return m_pInstance;
}

void CBallisticCalculator::DeleteInstance(void)
{
	if(m_pInstance)
	{
		delete m_pInstance;
		m_pInstance = 0;
	}
}
/////////////////////// Singleton Implementation Ends ///////////////////////



void CBallisticCalculator::PopulateDragModels(void)
{
	//G1 Drag Model
	this->G1Model.push_back(DragModelData(4230, 1.477404177730177e-04, 1.9565));
	this->G1Model.push_back(DragModelData(3680, 1.920339268755614e-04, 1.925 ));
	this->G1Model.push_back(DragModelData(3450, 2.894751026819746e-04, 1.875 ));
	this->G1Model.push_back(DragModelData(3295,	4.349905111115636e-04, 1.825 ));
	this->G1Model.push_back(DragModelData(3130,	6.520421871892662e-04, 1.775 ));
	this->G1Model.push_back(DragModelData(2960,	9.748073694078696e-04, 1.725 ));
	this->G1Model.push_back(DragModelData(2830,	1.453721560187286e-03, 1.675 ));
	this->G1Model.push_back(DragModelData(2680,	2.162887202930376e-03, 1.625 ));
	this->G1Model.push_back(DragModelData(2460,	3.209559783129881e-03, 1.575 ));
	this->G1Model.push_back(DragModelData(2225,	3.904368218691249e-03, 1.55  ));
	this->G1Model.push_back(DragModelData(2015,	3.222942271262336e-03, 1.575 ));
	this->G1Model.push_back(DragModelData(1890,	2.203329542297809e-03, 1.625 ));
	this->G1Model.push_back(DragModelData(1810,	1.511001028891904e-03, 1.675 ));
	this->G1Model.push_back(DragModelData(1730,	8.609957592468259e-04, 1.75  ));
	this->G1Model.push_back(DragModelData(1595,	4.086146797305117e-04, 1.85  ));
	this->G1Model.push_back(DragModelData(1520,	1.954473210037398e-04, 1.95  ));
	this->G1Model.push_back(DragModelData(1420,	5.431896266462351e-05, 2.125 ));
	this->G1Model.push_back(DragModelData(1360,	8.847742581674416e-06, 2.375 ));
	this->G1Model.push_back(DragModelData(1315,	1.456922328720298e-06, 2.625 ));
	this->G1Model.push_back(DragModelData(1280,	2.419485191895565e-07, 2.875 ));
	this->G1Model.push_back(DragModelData(1220,	1.657956321067612e-08, 3.25  ));
	this->G1Model.push_back(DragModelData(1185,	4.745469537157371e-10, 3.75  ));
	this->G1Model.push_back(DragModelData(1150,	1.379746590025088e-11, 4.25  ));
	this->G1Model.push_back(DragModelData(1100,	4.070157961147882e-13, 4.75  ));
	this->G1Model.push_back(DragModelData(1060,	2.938236954847331e-14, 5.125 ));
	this->G1Model.push_back(DragModelData(1025,	1.228597370774746e-14, 5.25  ));
	this->G1Model.push_back(DragModelData( 980,	2.916938264100495e-14, 5.125 ));
	this->G1Model.push_back(DragModelData( 945,	3.855099424807451e-13, 4.75  ));
	this->G1Model.push_back(DragModelData( 905,	1.185097045689854e-11, 4.25  ));
	this->G1Model.push_back(DragModelData( 860,	3.566129470974951e-10, 3.75  ));
	this->G1Model.push_back(DragModelData( 810,	1.045513263966272e-08, 3.25  ));
	this->G1Model.push_back(DragModelData( 780,	1.291159200846216e-07, 2.875 ));
	this->G1Model.push_back(DragModelData( 750,	6.824429329105383e-07, 2.625 ));
	this->G1Model.push_back(DragModelData( 700,	3.569169672385163e-06, 2.375 ));
	this->G1Model.push_back(DragModelData( 640,	1.839015095899579e-05, 2.125 ));
	this->G1Model.push_back(DragModelData( 600,	5.71117468873424e-05 , 1.950 ));
	this->G1Model.push_back(DragModelData( 550,	9.226557091973427e-05, 1.875 ));
	this->G1Model.push_back(DragModelData( 250,	9.337991957131389e-05, 1.875 ));
	this->G1Model.push_back(DragModelData(   0,	5.206214107320588e-05, 2.000 ));
	this->G1Model.push_back(DragModelData( 100,	7.225247327590413e-05, 1.925 ));
	this->G1Model.push_back(DragModelData(  65,	5.792684957074546e-05, 1.975 ));

	//G2 Drag Model
	this->G2Model.push_back(DragModelData( 1674, .0079470052136733   , 1.36999902851493 ));
	this->G2Model.push_back(DragModelData( 1172, 1.00419763721974e-03, 1.65392237010294 ));
	this->G2Model.push_back(DragModelData( 1060, 7.15571228255369e-23, 7.91913562392361 ));
	this->G2Model.push_back(DragModelData(  949, 1.39589807205091e-10, 3.81439537623717 ));
	this->G2Model.push_back(DragModelData(  670, 2.34364342818625e-04, 1.71869536324748 ));
	this->G2Model.push_back(DragModelData(  335, 1.77962438921838e-04, 1.76877550388679 ));
	this->G2Model.push_back(DragModelData(    0, 5.18033561289704e-05, 1.98160270524632 ));

	//G5 Drag Model
	this->G5Model.push_back(DragModelData( 1730, 7.24854775171929e-03, 1.41538574492812 ));
	this->G5Model.push_back(DragModelData( 1228, 3.50563361516117e-05, 2.13077307854948 ));
	this->G5Model.push_back(DragModelData( 1116, 1.84029481181151e-13, 4.81927320350395 ));
	this->G5Model.push_back(DragModelData( 1004, 1.34713064017409e-22, 7.8100555281422  ));
	this->G5Model.push_back(DragModelData(  837, 1.03965974081168e-07, 2.84204791809926 ));
	this->G5Model.push_back(DragModelData(  335, 1.09301593869823e-04, 1.81096361579504 ));
	this->G5Model.push_back(DragModelData(    0, 3.51963178524273e-05, 2.00477856801111 ));

	//G6 Drag Model
	this->G6Model.push_back(DragModelData( 3236, 0.0455384883480781   , 1.15997674041274 ));
	this->G6Model.push_back(DragModelData( 2065, 7.167261849653769e-02, 1.10704436538885 ));
	this->G6Model.push_back(DragModelData( 1311, 1.66676386084348e-03 , 1.60085100195952 ));
	this->G6Model.push_back(DragModelData( 1144, 1.01482730119215e-07 , 2.9569674731838  ));
	this->G6Model.push_back(DragModelData( 1004, 4.31542773103552e-18 , 6.34106317069757 ));
	this->G6Model.push_back(DragModelData(  670, 2.04835650496866e-05 , 2.11688446325998 ));
	this->G6Model.push_back(DragModelData(    0, 7.50912466084823e-05 , 1.92031057847052 ));

	//G7 Drag Model
	this->G7Model.push_back(DragModelData( 4200, 1.29081656775919e-09, 3.24121295355962 ));
	this->G7Model.push_back(DragModelData( 3000, 0.0171422231434847  , 1.27907168025204 ));
	this->G7Model.push_back(DragModelData( 1470, 2.33355948302505e-03, 1.52693913274526 ));
	this->G7Model.push_back(DragModelData( 1260, 7.97592111627665e-04, 1.67688974440324 ));
	this->G7Model.push_back(DragModelData( 1110, 5.71086414289273e-12, 4.3212826264889  ));
	this->G7Model.push_back(DragModelData(  960, 3.02865108244904e-17, 5.99074203776707 ));
	this->G7Model.push_back(DragModelData(  670, 7.52285155782535e-06, 2.1738019851075  ));
	this->G7Model.push_back(DragModelData(  540, 1.31766281225189e-05, 2.08774690257991 ));
	this->G7Model.push_back(DragModelData(    0, 1.34504843776525e-05, 2.08702306738884 ));

	//G8 Drag Model
	this->G8Model.push_back(DragModelData( 3571, .0112263766252305   , 1.33207346655961 ));
	this->G8Model.push_back(DragModelData( 1841, .0167252613732636   , 1.28662041261785 ));
	this->G8Model.push_back(DragModelData( 1120, 2.20172456619625e-03, 1.55636358091189 ));
	this->G8Model.push_back(DragModelData( 1088, 2.0538037167098e-16 , 5.80410776994789 ));
	this->G8Model.push_back(DragModelData(  976, 5.92182174254121e-12, 4.29275576134191 ));
	this->G8Model.push_back(DragModelData(    0, 4.3917343795117e-05 , 1.99978116283334 ));

}

double CBallisticCalculator::RetardationEstimation(DRAGTYPE drag, double DragCoefficient, double Velocity)
{
	CMath *Math = CMath::GetInstance();

	if((Velocity < 0) || (Velocity > 10000))
	{
		return -1;
	}

	if((Velocity == LastVelocity) && (drag == LastDragType) && (DragCoefficient == LastDragCoefficient))
	{
		return LastValue;
	}

	else
	{
		LastVelocity = Velocity;
		LastDragType = drag;
		LastDragCoefficient = DragCoefficient;
	}

	LastValue=-1;
	A=-1;
	M=-1;

	switch(drag)
	{
		case G1:
		{
			for(unsigned int i = 0; i < G1Model.size(); i++)
			{
				//If the Velocity is equal to a static value of the drag model
				if(G1Model[i].ProjectileVelocity == Velocity)
				{
					A = G1Model[i].A;
					M = G1Model[i].M;

					LastValue=A*pow(Velocity,M)/DragCoefficient;
					return LastValue;
				}
				
				//If the velocity is not greater than the current value of the drag model
				else if(G1Model[i].ProjectileVelocity > Velocity)
				{
					//do nothing and keep iterating
				}

				//Lerp the values since its between two data points
				else if(G1Model[i].ProjectileVelocity < Velocity)
				{
					if(i == 0)
					{
						A = G1Model[0].A;
						M = G1Model[0].M;

						LastValue=A*pow(Velocity,M)/DragCoefficient;
						return LastValue;
					}

					else
					{
						Progression = (Velocity-G1Model[i].ProjectileVelocity)/(G1Model[i-1].ProjectileVelocity-G1Model[i].ProjectileVelocity);

						A = Math->LinearInterpolationD(G1Model[i].A, G1Model[i-1].A, Progression);
						M = Math->LinearInterpolationD(G1Model[i].M, G1Model[i-1].M, Progression);

						LastValue=A*pow(Velocity,M)/DragCoefficient;
						return LastValue;

					}
				}
			}

			break;
			
		}

		case G2:
		{
			for(unsigned int i = 0; i < G2Model.size(); i++)
			{
				//If the Velocity is equal to a static value of the drag model
				if(G2Model[i].ProjectileVelocity == Velocity)
				{
					A = G2Model[i].A;
					M = G2Model[i].M;

					LastValue=A*pow(Velocity,M)/DragCoefficient;
					return LastValue;
				}
				
				//If the velocity is not greater than the current value of the drag model
				else if(G2Model[i].ProjectileVelocity > Velocity)
				{
					//do nothing and keep iterating
				}

				//Lerp the values since its between two data points
				else if(G2Model[i].ProjectileVelocity < Velocity)
				{
					if(i == 0)
					{
						A = G2Model[0].A;
						M = G2Model[0].M;

						LastValue=A*pow(Velocity,M)/DragCoefficient;
						return LastValue;
					}

					else
					{
						Progression = (Velocity-G2Model[i].ProjectileVelocity)/(G2Model[i-1].ProjectileVelocity-G2Model[i].ProjectileVelocity);

						A = Math->LinearInterpolationD(G2Model[i].A, G2Model[i-1].A, Progression);
						M = Math->LinearInterpolationD(G2Model[i].M, G2Model[i-1].M, Progression);

						LastValue=A*pow(Velocity,M)/DragCoefficient;
						return LastValue;

					}
				}
			}

			break;
		}
		case G5:
		{
			for(unsigned int i = 0; i < G5Model.size(); i++)
			{
				//If the Velocity is equal to a static value of the drag model
				if(G5Model[i].ProjectileVelocity == Velocity)
				{
					A = G5Model[i].A;
					M = G5Model[i].M;

					LastValue=A*pow(Velocity,M)/DragCoefficient;
					return LastValue;
				}
				
				//If the velocity is not greater than the current value of the drag model
				else if(G5Model[i].ProjectileVelocity > Velocity)
				{
					//do nothing and keep iterating
				}

				//Lerp the values since its between two data points
				else if(G5Model[i].ProjectileVelocity < Velocity)
				{
					if(i == 0)
					{
						A = G5Model[0].A;
						M = G5Model[0].M;

						LastValue=A*pow(Velocity,M)/DragCoefficient;
						return LastValue;
					}

					else
					{
						Progression = (Velocity-G5Model[i].ProjectileVelocity)/(G5Model[i-1].ProjectileVelocity-G5Model[i].ProjectileVelocity);

						A = Math->LinearInterpolationD(G5Model[i].A, G5Model[i-1].A, Progression);
						M = Math->LinearInterpolationD(G5Model[i].M, G5Model[i-1].M, Progression);

						LastValue=A*pow(Velocity,M)/DragCoefficient;
						return LastValue;

					}
				}
			}

			break;
		}
		case G6:
		{
			for(unsigned int i = 0; i < G6Model.size(); i++)
			{
				//If the Velocity is equal to a static value of the drag model
				if(G6Model[i].ProjectileVelocity == Velocity)
				{
					A = G6Model[i].A;
					M = G6Model[i].M;

					LastValue=A*pow(Velocity,M)/DragCoefficient;
					return LastValue;
				}
				
				//If the velocity is not greater than the current value of the drag model
				else if(G6Model[i].ProjectileVelocity > Velocity)
				{
					//do nothing and keep iterating
				}

				//Lerp the values since its between two data points
				else if(G6Model[i].ProjectileVelocity < Velocity)
				{
					if(i == 0)
					{
						A = G6Model[0].A;
						M = G6Model[0].M;

						LastValue=A*pow(Velocity,M)/DragCoefficient;
						return LastValue;
					}

					else
					{
						Progression = (Velocity-G6Model[i].ProjectileVelocity)/(G6Model[i-1].ProjectileVelocity-G6Model[i].ProjectileVelocity);

						A = Math->LinearInterpolationD(G6Model[i].A, G6Model[i-1].A, Progression);
						M = Math->LinearInterpolationD(G6Model[i].M, G6Model[i-1].M, Progression);

						LastValue=A*pow(Velocity,M)/DragCoefficient;
						return LastValue;

					}
				}
			}

			break;
		}
		case G7:
		{
			for(unsigned int i = 0; i < G7Model.size(); i++)
			{
				//If the Velocity is equal to a static value of the drag model
				if(G7Model[i].ProjectileVelocity == Velocity)
				{
					A = G7Model[i].A;
					M = G7Model[i].M;

					LastValue=A*pow(Velocity,M)/DragCoefficient;
					return LastValue;
				}
				
				//If the velocity is not greater than the current value of the drag model
				else if(G7Model[i].ProjectileVelocity > Velocity)
				{
					//do nothing and keep iterating
				}

				//Lerp the values since its between two data points
				else if(G7Model[i].ProjectileVelocity < Velocity)
				{
					if(i == 0)
					{
						A = G7Model[0].A;
						M = G7Model[0].M;

						LastValue=A*pow(Velocity,M)/DragCoefficient;
						return LastValue;
					}

					else
					{
						Progression = (Velocity-G7Model[i].ProjectileVelocity)/(G7Model[i-1].ProjectileVelocity-G7Model[i].ProjectileVelocity);

						A = Math->LinearInterpolationD(G7Model[i].A, G7Model[i-1].A, Progression);
						M = Math->LinearInterpolationD(G7Model[i].M, G7Model[i-1].M, Progression);

						LastValue=A*pow(Velocity,M)/DragCoefficient;
						return LastValue;

					}
				}
			}

			break;
		}
		case G8:
		{
			for(unsigned int i = 0; i < G8Model.size(); i++)
			{
				//If the Velocity is equal to a static value of the drag model
				if(G8Model[i].ProjectileVelocity == Velocity)
				{
					A = G8Model[i].A;
					M = G8Model[i].M;

					LastValue=A*pow(Velocity,M)/DragCoefficient;
					return LastValue;
				}
				
				//If the velocity is not greater than the current value of the drag model
				else if(G8Model[i].ProjectileVelocity > Velocity)
				{
					//do nothing and keep iterating
				}

				//Lerp the values since its between two data points
				else if(G8Model[i].ProjectileVelocity < Velocity)
				{
					if(i == 0)
					{
						A = G8Model[0].A;
						M = G8Model[0].M;

						LastValue=A*pow(Velocity,M)/DragCoefficient;
						return LastValue;
					}

					else
					{
						Progression = (Velocity-G8Model[i].ProjectileVelocity)/(G8Model[i-1].ProjectileVelocity-G8Model[i].ProjectileVelocity);

						A = Math->LinearInterpolationD(G8Model[i].A, G8Model[i-1].A, Progression);
						M = Math->LinearInterpolationD(G8Model[i].M, G8Model[i-1].M, Progression);

						LastValue=A*pow(Velocity,M)/DragCoefficient;
						return LastValue;

					}
				}
			}

			break;
		}
	}
}

DragModelData CBallisticCalculator::Retard(DRAGTYPE drag, double DragCoefficient, double Velocity)
{
	CMath *Math = CMath::GetInstance();

	LastValue=-1;
	A=-1;
	M=-1;

	if((Velocity < 0) || (Velocity > 10000))
	{
		return -1;
	}

	switch(drag)
	{
		case G1:
		{
			for(unsigned int i = 0; i < G1Model.size(); i++)
			{
				//If the Velocity is equal to a static value of the drag model
				if(G1Model[i].ProjectileVelocity == Velocity)
				{
					RetardValue.A = G1Model[i].A;
					RetardValue.M = G1Model[i].M;
					RetardValue.ProjectileVelocity = Velocity;

					return this->RetardValue;
				}
				
				//If the velocity is not greater than the current value of the drag model
				else if(G1Model[i].ProjectileVelocity > Velocity)
				{
					//do nothing and keep iterating
				}

				//Lerp the values since its between two data points
				else if(G1Model[i].ProjectileVelocity < Velocity)
				{

					if(i == 0)
					{
						RetardValue.A = G1Model[0].A;
						RetardValue.M = G1Model[0].M;
						RetardValue.ProjectileVelocity = Velocity;

						return this->RetardValue;
					}

					else
					{

						Progression = (Velocity-G1Model[i].ProjectileVelocity)/(G1Model[i-1].ProjectileVelocity-G1Model[i].ProjectileVelocity);

						RetardValue.A = Math->LinearInterpolationD(G1Model[i].A, G1Model[i-1].A, Progression);
						RetardValue.M = Math->LinearInterpolationD(G1Model[i].M, G1Model[i-1].M, Progression);
						
						RetardValue.ProjectileVelocity = Velocity;

						return this->RetardValue;
					}
				}
			}

			break;
		}

		case G2:
		{
			for(unsigned int i = 0; i < G2Model.size(); i++)
			{
				//If the Velocity is equal to a static value of the drag model
				if(G2Model[i].ProjectileVelocity == Velocity)
				{
					RetardValue.A = G2Model[i].A;
					RetardValue.M = G2Model[i].M;
					RetardValue.ProjectileVelocity = Velocity;

					return this->RetardValue;
				}
				
				//If the velocity is not greater than the current value of the drag model
				else if(G2Model[i].ProjectileVelocity > Velocity)
				{
					//do nothing and keep iterating
				}

				//Lerp the values since its between two data points
				else if(G2Model[i].ProjectileVelocity < Velocity)
				{

					if(i == 0)
					{
						RetardValue.A = G2Model[0].A;
						RetardValue.M = G2Model[0].M;
						RetardValue.ProjectileVelocity = Velocity;

						return this->RetardValue;
					}

					else
					{

						Progression = (Velocity-G2Model[i].ProjectileVelocity)/(G2Model[i-1].ProjectileVelocity-G2Model[i].ProjectileVelocity);

						RetardValue.A = Math->LinearInterpolationD(G2Model[i].A, G2Model[i-1].A, Progression);
						RetardValue.M = Math->LinearInterpolationD(G2Model[i].M, G2Model[i-1].M, Progression);
						
						RetardValue.ProjectileVelocity = Velocity;

						return this->RetardValue;
					}
				}
			}

			break;
		}
		case G5:
		{
			for(unsigned int i = 0; i < G5Model.size(); i++)
			{
				//If the Velocity is equal to a static value of the drag model
				if(G5Model[i].ProjectileVelocity == Velocity)
				{
					RetardValue.A = G5Model[i].A;
					RetardValue.M = G5Model[i].M;
					RetardValue.ProjectileVelocity = Velocity;

					return this->RetardValue;
				}
				
				//If the velocity is not greater than the current value of the drag model
				else if(G5Model[i].ProjectileVelocity > Velocity)
				{
					//do nothing and keep iterating
				}

				//Lerp the values since its between two data points
				else if(G5Model[i].ProjectileVelocity < Velocity)
				{

					if(i == 0)
					{
						RetardValue.A = G5Model[0].A;
						RetardValue.M = G5Model[0].M;
						RetardValue.ProjectileVelocity = Velocity;

						return this->RetardValue;
					}

					else
					{

						Progression = (Velocity-G5Model[i].ProjectileVelocity)/(G5Model[i-1].ProjectileVelocity-G5Model[i].ProjectileVelocity);

						RetardValue.A = Math->LinearInterpolationD(G5Model[i].A, G5Model[i-1].A, Progression);
						RetardValue.M = Math->LinearInterpolationD(G5Model[i].M, G5Model[i-1].M, Progression);
						
						RetardValue.ProjectileVelocity = Velocity;

						return this->RetardValue;
					}
				}
			}

			break;
		}
		case G6:
		{
			for(unsigned int i = 0; i < G6Model.size(); i++)
			{
				//If the Velocity is equal to a static value of the drag model
				if(G6Model[i].ProjectileVelocity == Velocity)
				{
					RetardValue.A = G6Model[i].A;
					RetardValue.M = G6Model[i].M;
					RetardValue.ProjectileVelocity = Velocity;

					return this->RetardValue;
				}
				
				//If the velocity is not greater than the current value of the drag model
				else if(G6Model[i].ProjectileVelocity > Velocity)
				{
					//do nothing and keep iterating
				}

				//Lerp the values since its between two data points
				else if(G6Model[i].ProjectileVelocity < Velocity)
				{

					if(i == 0)
					{
						RetardValue.A = G6Model[0].A;
						RetardValue.M = G6Model[0].M;
						RetardValue.ProjectileVelocity = Velocity;

						return this->RetardValue;
					}

					else
					{

						Progression = (Velocity-G6Model[i].ProjectileVelocity)/(G6Model[i-1].ProjectileVelocity-G6Model[i].ProjectileVelocity);

						RetardValue.A = Math->LinearInterpolationD(G6Model[i].A, G6Model[i-1].A, Progression);
						RetardValue.M = Math->LinearInterpolationD(G6Model[i].M, G6Model[i-1].M, Progression);
						
						RetardValue.ProjectileVelocity = Velocity;

						return this->RetardValue;
					}
				}
			}

			break;
		}
		case G7:
		{
			for(unsigned int i = 0; i < G7Model.size(); i++)
			{
				//If the Velocity is equal to a static value of the drag model
				if(G7Model[i].ProjectileVelocity == Velocity)
				{
					RetardValue.A = G7Model[i].A;
					RetardValue.M = G7Model[i].M;
					RetardValue.ProjectileVelocity = Velocity;

					return this->RetardValue;
				}
				
				//If the velocity is not greater than the current value of the drag model
				else if(G7Model[i].ProjectileVelocity > Velocity)
				{
					//do nothing and keep iterating
				}

				//Lerp the values since its between two data points
				else if(G7Model[i].ProjectileVelocity < Velocity)
				{

					if(i == 0)
					{
						RetardValue.A = G7Model[0].A;
						RetardValue.M = G7Model[0].M;
						RetardValue.ProjectileVelocity = Velocity;

						return this->RetardValue;
					}

					else
					{

						Progression = (Velocity-G7Model[i].ProjectileVelocity)/(G7Model[i-1].ProjectileVelocity-G7Model[i].ProjectileVelocity);

						RetardValue.A = Math->LinearInterpolationD(G7Model[i].A, G7Model[i-1].A, Progression);
						RetardValue.M = Math->LinearInterpolationD(G7Model[i].M, G7Model[i-1].M, Progression);
						
						RetardValue.ProjectileVelocity = Velocity;

						return this->RetardValue;
					}
				}
			}

			break;
		}
		case G8:
		{
			for(unsigned int i = 0; i < G8Model.size(); i++)
			{
				//If the Velocity is equal to a static value of the drag model
				if(G8Model[i].ProjectileVelocity == Velocity)
				{
					RetardValue.A = G8Model[i].A;
					RetardValue.M = G8Model[i].M;
					RetardValue.ProjectileVelocity = Velocity;

					return this->RetardValue;
				}
				
				//If the velocity is not greater than the current value of the drag model
				else if(G8Model[i].ProjectileVelocity > Velocity)
				{
					//do nothing and keep iterating
				}

				//Lerp the values since its between two data points
				else if(G8Model[i].ProjectileVelocity < Velocity)
				{

					if(i == 0)
					{
						RetardValue.A = G8Model[0].A;
						RetardValue.M = G8Model[0].M;
						RetardValue.ProjectileVelocity = Velocity;

						return this->RetardValue;
					}

					else
					{

						Progression = (Velocity-G8Model[i].ProjectileVelocity)/(G8Model[i-1].ProjectileVelocity-G8Model[i].ProjectileVelocity);

						RetardValue.A = Math->LinearInterpolationD(G8Model[i].A, G8Model[i-1].A, Progression);
						RetardValue.M = Math->LinearInterpolationD(G8Model[i].M, G8Model[i-1].M, Progression);
						
						RetardValue.ProjectileVelocity = Velocity;

						return this->RetardValue;
					}
				}
			}

			break;
		}
	}
}